#include<stdio.h>
// #include<stdlib.h>
// #include<string.h>
#include"BigNumber.h"
using namespace std;

int main(void)
{
    /*p和q是保密的大素数,n为p和q的乘积,t为n的欧拉函数值(phi(n)=(p-1)(q-1)),e为公钥整数257,d为私钥,a为明文,b为密文,c为解密后结果*/
    BigNum e(257),n,d,a,b,c;
    srand((unsigned)time(NULL)); 
    cout<<"Program start..."<<endl<<endl;

    /*密钥的产生:
    1.选两个保密的大素数p和q;
    2.计算n=p*q,phi(n)=(p-1)*(q-1),其中phi(n)是n的欧拉函数值;
    3.选一整数e,满足1<e<phi(n),且ged(phi(n),e)=1;
    4.计算d,满足d·e=1 mod phi(n),即d是e在模phi(n)下的乘法逆元,因e与phi(n)互素,由模运算可知,它的乘法逆元一定存在;
    5.以(e,n)为公钥,以(d,n)为私钥
    */
    if (false) //产生随机密钥
    {
        BigNum p,q,I(1),t,temp,O(0);
        p.GeneratePrime();   //产生素数
        q.GeneratePrime();
        while(p==q)   //判断两个素数不等
            q.GeneratePrime();
        temp=p-I;
        t=q-I;
        t=t*temp;
        cout<<"The prime number p (32 * 32 digits) is:"<<endl;
        p.print();
        cout<<endl;
        cout<<"The prime number q (32 * 32 digits) is:"<<endl;
        q.print();
        cout<<endl;
        cout<<"Public key n (64 * 32 bits) is:"<<endl;
        n=p*q;
        n.print();
        n.ArrayOrder();//正确的公钥
        cout<<endl;
        cout<<"Public key e (decimal is 257) is:"<<endl;
        e.print();
        cout<<endl;
        d.ex_euclid(e,t);   //计算私钥d
        cout<<"Private key d (64 * 32 bits) is:"<<endl;
        d.print();
        d.ArrayOrder();//正确的私钥
        cout<<endl;
    }
    else //设定公钥私钥(使用正确的公钥和正确的私钥)
    {
        unsigned long PublicKey[64]={
            0xcfe13dbb, 0xd2f10445, 0x68528845, 0x5334689f, 0xfb1d791a, 0xfb87529c, 0x39b67e50, 0xfa59154f, 
            0xec006fe2, 0x9f3696b7, 0x65880a09, 0x69f1d443, 0x924b4404, 0x1040c230, 0xc12e04, 0x5be112cd, 
            0x7887a62, 0x93824d72, 0x414752d9, 0x6579af69, 0x57e34731, 0x24f173ad, 0xdbb89071, 0x80dd2301, 
            0x85031a16, 0x189ab9f6, 0xfda8aa1f, 0x2282ab0c, 0x8df33e80, 0xbdd5a3a9, 0xd8e7b530, 0xf795a53d, 
            0xda0f2293, 0xa2303b3c, 0x58301021, 0x8dfb4687, 0xfe77ae2a, 0x27386f9e, 0x8e60ae73, 0xb376c271, 
            0xa1d6a1da, 0x78caef1c, 0x4e780e5b, 0x8df88ac3, 0xad54c79e, 0x6649bc3e, 0xa52a0db8, 0xee38ced4, 
            0x3895d8ef, 0xf96bdf2e, 0xd6097ca6, 0x5823ad9b, 0x1ab133ec, 0x957583b, 0x3426052c, 0xb5f70758, 
            0xa717cef4, 0x2e6606de, 0xf7066b45, 0xbf4758c3, 0xd2034302, 0x60052e01, 0x54ac1fe, 0x78045771
        };

        unsigned long PrivateKey[64]={
            0xb6eab871, 0x870e227d, 0x23d9c816, 0xd5478d9a, 0xab314ebe, 0x765399a7, 0x8155f37b, 0x945e492d, 
            0x16cd8968, 0xda1cead, 0xcd964e57, 0x726b5f2, 0x3d0edce5, 0xdb8b4acb, 0xe654ccb6, 0x1ee2ed33, 
            0xbb09fdb0, 0x2440983a, 0x8354be7e, 0xa8bff335, 0x51ce48fd, 0x6ee0575a, 0x9d8dd990, 0x481e5973, 
            0xdb3402bf, 0xe807a26d, 0xe4c655b8, 0x76a43aa9, 0x24a0f26b, 0xb416b393, 0x84ae608b, 0x7afee36b, 
            0x1f2b1937, 0xa3847413, 0x1826449, 0xe9e02b09, 0x382568b4, 0x79c39a9d, 0xf3010734, 0x93bb7111, 
            0x2dd509fa, 0x51b254ad, 0x2b52638e, 0xa127c1b3, 0x4c78a205, 0x1d3d4aa7, 0x6af8713d, 0x208302a1, 
            0xfd709b38, 0xdf674325, 0xb945943, 0x205e677b, 0x719bc3bc, 0x34a98107, 0xf6a11d07, 0x8acd7b8e, 
            0x3cf2e8c8, 0xdb5ae3f4, 0x4107a0c9, 0x86acdde3, 0xbe37229c, 0xa71b0a02, 0xe34da6ac, 0x31804be8
        };

        if (false)
        {
            memcpy(n.array,PublicKey,sizeof(PublicKey));
            memcpy(d.array,PrivateKey,sizeof(PrivateKey));   
        }
        else
        {
            for (int i = 0; i < 64; i++)
            {
                n.array[i]=PublicKey[i];
                d.array[i]=PrivateKey[i];
            }   
        }

        n.length=64;
        d.length=64;

        cout<<"Public key n (64 * 32 bits) is:"<<endl;
        n.print();
        cout<<endl;
        cout<<"Public key e (decimal is 257) is:"<<endl;
        e.print();
        cout<<endl;
        cout<<"Private key d (64 * 32 bits) is:"<<endl;
        d.print();
        cout<<endl;
    }
    
    /*加密:
    1.加密时首先将明文比特串分组，使得每个分组对应的十进制数小于n,即分组长度小于log(n)/log(2);
    2.然后对每个明文分组m作加密运算:c=m^e mod n
    */
    if (true)
    {
        //读取密码
        string temp,A;

        if (false)
        {
            ifstream myfile("key.txt",ios::in); 
            if (!myfile.is_open()) 
            { 
                cout<<"Cannot open file"<<endl; 
            }
            string res;
            while(getline(myfile,temp)){
                A+=temp;
                A+='\n';
            }
            myfile.close();
        }
        else
        {
            A="adfe12733a16c7c702edcf00b45bdebe\n";
        }

        a=BigNum(A);
        cout<<"The Key is:"<<endl;
        cout<<A;
        cout<<endl;

        //产生密文b
        b=a.power_mod(e,n);
        cout<<"Encrypted ciphertext b (64 * 32 bits) is:"<<endl;
        b.print();
        cout<<endl;
    }

    /*解密:
    1.对密文分组的解密运算为:m=c^d mod n
    */
    if (true)
    {
        //解密Key
        c=b.power_mod(d,n);
        cout<<"Plaintext decoded is:"<<endl;
        c.printS();
        cout<<endl;
    }
    
    return 0;
}